import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:provider/provider.dart';
import 'package:spendbook/common/vertical_tabs.dart';
import 'package:spendbook/common/constants.dart';
import 'package:spendbook/common/icons.dart';
import 'package:spendbook/models/chart.dart';
import 'package:spendbook/models/family.dart';
import 'package:spendbook/models/user.dart';

class ChartScreen extends StatefulWidget {
  @override
  _ChartScreenState createState() => _ChartScreenState();
}

class _ChartScreenState extends State<ChartScreen> {
  bool _loaded = false;
  Map<String, Family> _families = {};
  List<Map<String, dynamic>> _statistics = [];
  List<Map<String, dynamic>> _records = [];
  List<Map<String, dynamic>> _projects = [];
  List<Map<String, dynamic>> _incomes = [];
  List<Map<String, dynamic>> _cards = [];
  List<Indicator> _indicators = [];
  List<Choice> _choices = [];
  bool _isIncome = false;

  @override
  void initState() {
    SystemChrome.setPreferredOrientations([DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]);
    super.initState();
    _choices.addAll(choices);
    _choices.insert(0, new Choice(title: '总览', icon: IconFont.notebook));
    initData();
  }

  void dispose() {
    super.dispose();
    SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]);
  }

  Future initData() async {
    List _list = await Family().fetch();
    _list.forEach((_item) {
      final Family _family = Family()..fromJson(_item);
      _families[_family.family!.id.toString()] = _family;

      _indicators.add(
        Indicator(
          color: colorList[_family.family!.id! % 8],
          text: _family.nickname,
          textColor: Theme.of(context).colorScheme.secondary,
          isSquare: true,
        ),
      );
    });
    final _user = context.read<User>();
    _indicators.insert(
      0,
      Indicator(
        color: colorList[_user.id! % 8],
        text: '我',
        textColor: Theme.of(context).colorScheme.secondary,
        isSquare: true,
      ),
    );
    await initStatistics();
    await initRecord();
    await initFinance();
    await initDeposit();
    setState(() {
      _loaded = true;
    });
  }

  Future initStatistics() async {
    List<dynamic> _list = await Chart().statistics();
    _list.forEach((_item) {
      double value = 0;
      double total = 0;
      List<BarChartRodStackItem> stacks = [];
      List<Map<String, dynamic>> data = [];
      (_item as Map<String, dynamic>).forEach((_id, _fee) {
        _fee = _fee ?? 0;
        stacks.add(BarChartRodStackItem(value, _fee / 1000000, colorList[int.parse(_id) % 8]));
        value += _fee / 1000000;
        total += _fee;
        data.insert(0, {'name': _families[_id] == null ? '我' : _families[_id]!.nickname, 'fee': _fee});
      });

      _statistics.add({'value': value, 'total': total, 'stacks': stacks, 'data': data});
    });
  }

  Future initRecord() async {
    List<dynamic> _list = await Chart().record();
    _list.forEach((_item) {
      double value = 0;
      double total = 0;
      List<BarChartRodStackItem> stacks = [];
      List<Map<String, dynamic>> data = [];
      (_item as Map<String, dynamic>).forEach((_id, _fee) {
        stacks.add(BarChartRodStackItem(value, _fee / 1000, colorList[int.parse(_id) % 8]));
        value += _fee / 1000;
        total += _fee;
        data.insert(0, {'name': _families[_id] == null ? '我' : _families[_id]!.nickname, 'fee': _fee});
      });

      _records.add({'value': value, 'total': total, 'stacks': stacks, 'data': data});
    });
  }

  Future initFinance() async {
    Map<String, dynamic> _list = await Chart().project();
    double _sum = 0;
    _list.forEach((_id, _data) => _sum += _data['fee']);
    _list.forEach((_id, _data) {
      _projects.add({
        'color': colorList[int.parse(_id) % 8],
        'value': _data['fee'] / _sum * 100,
        'title': toStringAsMoney(double.parse(_data['fee'].toString()), fractionDigits: 1),
      });
      _incomes.add({
        'color': colorList[int.parse(_id) % 8],
        'value': _data['income'] / _sum * 100,
        'title': toStringAsMoney(double.parse(_data['income'].toString()), fractionDigits: 1),
      });
    });
  }

  Future initDeposit() async {
    Map<String, dynamic> _list = await Chart().card();
    double _sum = 0;
    _list.forEach((_id, _fee) => _sum += _fee);
    _list.forEach((_id, _fee) {
      _cards.add({
        'color': colorList[int.parse(_id) % 8],
        'value': _fee / _sum * 100,
        'title': toStringAsMoney(double.parse(_fee.toString()), fractionDigits: 1),
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('我的统计'),
      ),
      body: _loaded
          ? VerticalTabs(
              tabsWidth: 150,
              contentScrollAxis: Axis.vertical,
              indicatorColor: Theme.of(context).primaryColor,
              selectedTabBackgroundColor: Theme.of(context).primaryColor.withAlpha(15),
              tabs: _choices.map((choice) => Tab(text: choice.title, icon: Icon(choice.icon))).toList(),
              contents: <Widget>[
                Container(
                  padding: EdgeInsets.symmetric(horizontal: 20),
                  child: BarItem(
                    data: _statistics,
                    indicators: _indicators,
                    unit: 'm',
                    interval: 1,
                    maxY: 10,
                  ),
                ),
                Container(
                  padding: EdgeInsets.symmetric(horizontal: 20),
                  child: BarItem(
                    data: _records,
                    indicators: _indicators,
                  ),
                ),
                PieItem(
                  data: _isIncome ? _incomes : _projects,
                  indicators: _indicators,
                  title: Row(
                    children: <Widget>[
                      Text('本金'),
                      Switch(
                          value: _isIncome,
                          inactiveThumbColor: Theme.of(context).colorScheme.secondary,
                          inactiveTrackColor: Theme.of(context).colorScheme.secondary.withAlpha(0x80),
                          onChanged: (val) {
                            setState(() {
                              _isIncome = val;
                            });
                          }),
                      Text('收益')
                    ],
                  ),
                ),
                PieItem(
                  data: _cards,
                  indicators: _indicators,
                ),
              ],
            )
          : Center(
              child: Text(
                '正在加载中...',
                style: TextStyle(fontFamily: 'HappyFont', fontSize: 16),
              ),
            ),
    );
  }
}

class BarItem extends StatefulWidget {
  BarItem({Key? key, required this.data, required this.indicators, this.unit = 'k', this.interval = 5, this.maxY = 20}) : super(key: key);

  final List<Map<String, dynamic>> data;

  final List<Widget> indicators;

  final String unit;

  final double interval;

  final double maxY;

  @override
  _BarItemState createState() => _BarItemState();
}

class _BarItemState extends State<BarItem> {
  int? touchedIndex;

  @override
  Widget build(BuildContext context) {
    int i = 0;
    return Container(
        padding: EdgeInsets.symmetric(vertical: 16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: <Widget>[
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: widget.indicators,
            ),
            SizedBox(
              height: 16,
            ),
            Expanded(
              flex: 1,
              child: BarChart(
                BarChartData(
                  maxY: widget.maxY,
                  alignment: BarChartAlignment.center,
                  barTouchData: BarTouchData(
                      touchTooltipData: BarTouchTooltipData(
                          getTooltipColor: (data) => Colors.blueGrey,
                          getTooltipItem: (group, groupIndex, rod, rodIndex) {
                            final List<Map<String, dynamic>> _data = widget.data[groupIndex]['data'];
                            final List<String> _strings = _data.map((_item) => '${_item['name'].toString()}:${toStringAsMoney(double.parse(_item['fee'].toString()))}').toList();
                            _strings.add('共:' + toStringAsMoney(widget.data[groupIndex]['total']));
                            return BarTooltipItem(_strings.join('\n'), TextStyle(color: Colors.yellow));
                          }),
                      touchCallback: (e, barTouchResponse) {
                        setState(() {
                          if (barTouchResponse!.spot != null) {
                            touchedIndex = barTouchResponse.spot!.touchedBarGroupIndex;
                          } else {
                            touchedIndex = -1;
                          }
                        });
                      }),
                  titlesData: FlTitlesData(
                    show: true,
                    bottomTitles: AxisTitles(
                        sideTitles: SideTitles(
                            showTitles: true,
                            getTitlesWidget: (value, meta) {
                              return Padding(
                                padding: EdgeInsets.all(5),
                                child: Text(
                                  monthMap[value.toInt()],
                                  style: TextStyle(color: const Color(0xff939393), fontSize: 12),
                                ),
                              );
                            })),
                    leftTitles: AxisTitles(
                        sideTitles: SideTitles(
                      showTitles: true,
                      getTitlesWidget: (value, meta) {
                        return Text(
                          value == 0 ? '' : '${value.toInt()}' + widget.unit,
                          style: TextStyle(
                              color: const Color(
                                0xff939393,
                              ),
                              fontSize: 12),
                        );
                      },
                      interval: widget.interval,
                    )),
                  ),
                  gridData: FlGridData(
                    show: true,
                    checkToShowHorizontalLine: (value) => value % widget.interval == 0,
                    getDrawingHorizontalLine: (value) => FlLine(
                      color: Color(0xffe7e8ec),
                      strokeWidth: 1,
                    ),
                  ),
                  borderData: FlBorderData(
                    show: false,
                  ),
                  groupsSpace: 30,
                  barGroups: widget.data.map((item) {
                    final _isTouched = i == touchedIndex;
                    return BarChartGroupData(
                      x: i++,
                      barRods: [
                        BarChartRodData(toY: item['value'], width: _isTouched ? 10 : 8, rodStackItems: item['stacks']),
                      ],
                    );
                  }).toList(),
                ),
              ),
            ),
          ],
        ));
  }
}

class PieItem extends StatefulWidget {
  PieItem({Key? key, required this.data, required this.indicators, this.title}) : super(key: key);

  final List<Map<String, dynamic>> data;

  final List<Widget> indicators;

  final Widget? title;

  @override
  _PieItemState createState() => _PieItemState();
}

class _PieItemState extends State<PieItem> {
  int? touchedIndex;

  @override
  Widget build(BuildContext context) {
    int i = 0;
    return Row(
      children: <Widget>[
        SizedBox(
          width: 160,
          child: Padding(
            padding: EdgeInsets.all(20),
            child: Column(
              children: <Widget>[
                widget.title ?? Container(),
                Column(
                  children: widget.indicators,
                ),
              ],
            ),
          ),
        ),
        Expanded(
          child: PieChart(
            PieChartData(
                pieTouchData: PieTouchData(touchCallback: (e, pieTouchResponse) {
                  setState(() {
                    // if (e.touchInput is FlLongPressEnd || pieTouchResponse.touchInput is FlPanEnd) {
                    if (pieTouchResponse != null) {
                      touchedIndex = -1;
                    } else {
                      touchedIndex = pieTouchResponse!.touchedSection!.touchedSectionIndex;
                    }
                  });
                }),
                borderData: FlBorderData(
                  show: false,
                ),
                sectionsSpace: 0,
                centerSpaceRadius: 60,
                sections: widget.data.map((item) {
                  final isTouched = i++ == touchedIndex;
                  return PieChartSectionData(
                    color: item['color'],
                    value: item['value'],
                    title: item['title'],
                    radius: isTouched ? 80 : 60,
                    titleStyle: TextStyle(fontSize: isTouched ? 20 : 12, fontWeight: FontWeight.bold, color: Colors.white),
                  );
                }).toList()),
          ),
        ),
      ],
    );
  }
}

class Indicator extends StatelessWidget {
  final Color? color;
  final String text;
  final bool isSquare;
  final double size;
  final Color textColor;

  const Indicator({
    Key? key,
    this.color,
    required this.text,
    this.isSquare = false,
    this.size = 16,
    this.textColor = const Color(0xff505050),
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Row(
      children: <Widget>[
        Container(
          width: size,
          height: size,
          decoration: BoxDecoration(
            shape: isSquare ? BoxShape.rectangle : BoxShape.circle,
            color: color,
          ),
        ),
        const SizedBox(
          width: 4,
        ),
        Text(
          text,
          style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: textColor),
        )
      ],
    );
  }
}
